package com.moon.game.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.moon.game.cache.LRUCache;
import com.moon.game.constants.Constants;
import com.moon.game.exception.GException;
import com.moon.game.manager.ItemMG;
import com.moon.game.profile.ProfileService;
import com.moon.game.resource.model.Item;
import com.moon.game.util.Utils;
import com.moon.game.vos.PlayerVo;

/**
 * @description 普通道具操作
 * @author Ranger 作者 E-mail:haozi000005@163.com
 * @version 创建时间：2012-5-10 下午1:21:48
 */
public class ItemService {
	
	private static final Logger log = Logger.getLogger(ItemService.class);
	private static LRUCache<String, ArrayList<Item>> itemCache = new LRUCache<String, ArrayList<Item>>(500);
	/**
	 * 根据id获取人物playeritems
	 * @param playerId
	 * @return
	 */
	public static ArrayList<Item> getAllItems(String playerId) {
		try {
			//先从内存中获取道具，不存在则从db中获取
			ArrayList<Item> itemList = itemCache.get(playerId);
			if (itemList == null || itemList.size() == 0) {
				itemList = ProfileService.getItemsFromDB(playerId);
				itemCache.set(playerId, itemList);
			}
			return itemList;
		} catch (GException e1) {
			e1.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 根据id获取人物playeritems
	 * @param playerId
	 * @return
	 */
	public static Item getItem(String playerId, int itemId) {
		ArrayList<Item> itemList = getAllItems(playerId);
		if (itemList == null) {
			return null;
		}
		Item retItem = new Item();
		for (Item item : itemList) {
			if (itemId == item.getId()) {
				Utils.copyProperties(retItem, item);
				return retItem;
			}
		}
		return null;
	}
	
	/**
	 * 批量查询指定id列表的道具
	 * 
	 * @param playerId
	 * @param itemId
	 * @return 如果没有该道具num字段为0
	 */
	public static List<Item> QueryItems(String playerId, List<Integer> itemIds) {
		List<Item> queryResult = new ArrayList<Item>();
		for (Integer itemId : itemIds) {
			Item item = getItem(playerId, itemId);
			if (item == null) {
				Item nullItem = ItemMG.instance.itemFactory(itemId);
				nullItem.setNum(0);//没有该道具
				queryResult.add(nullItem);
			}else {
				queryResult.add(item);
			}
		}
		return queryResult;
	}
	
	/**
	 * 添加道具及其数量
	 * 
	 * @param player
	 * @param itemId 道具id
	 * @param num 添加数量
	 * @param checkRoom 是否检查行囊空间
	 * @return(1保存成功，4空间不够，3保存异常)
	 */
	public static int addItem(PlayerVo player, int itemId, int num, boolean checkRoom) {
		ArrayList<Item> items = getAllItems(player.getId());
		ArrayList<Item> newItems = new ArrayList<Item>();
		final Item item = ItemMG.instance.getItem(itemId);
		if (checkRoom && !checkRoom(player,items,num)) {
			return Constants.ADD_ITEM_NO_ROOM;
		}else {
			item.setNum(num);
			log.debug("try to add item:" + itemId);
			if (items != null && items.size() > 0) {
				boolean hasTheItem = false;
				for (Item hasItem : items) {
					Item newItem = ItemMG.instance.itemFactory(itemId);
					if (hasItem.getId() == itemId) {
						newItem.setNum(hasItem.getNum() + num);
						newItems.add(newItem);
						hasTheItem = true;
					}else {
						newItems.add(hasItem);
					}
				}
				if (!hasTheItem) {
					newItems.add(item);
				}
			}else {
				newItems.add(item);
			}
			try {
				syncItems(player.getId(), newItems);
				log.debug("add item:[" + itemId + "]success!");
				return Constants.ADD_ITEM_SUCC;
			} catch (GException e) {
				e.printStackTrace();
				return Constants.ADD_ITEM_FAIL;
			}
		}
	}
	
	/**
	 * 批量添加道具及其数量
	 * 
	 * @param player
	 * @param itemIds 道具id列表
	 * @param nums 数量列表
	 * @param checkRoom 是否检查行囊空间
	 * @return (1保存成功，4空间不够，3保存异常)
	 */
	public static int addItems(PlayerVo player, List<Integer> itemIds, List<Integer> nums, boolean checkRoom) {
		StringBuffer sb = new StringBuffer();
		ArrayList<Item> items = getAllItems(player.getId());
		ArrayList<Item> newItems = new ArrayList<Item>();
		HashMap<Integer, Item> hasItemMap = new HashMap<Integer, Item>();
		if (items != null) {
			for (final Item hasItem : items) {
				hasItemMap.put(hasItem.getId(), hasItem);
			}
		}
		if (itemIds == null || itemIds.size() == 0) {
			return Constants.ADD_ITEM_SUCC;
		}
		
		//行囊空间检测
		int addNum = 0;
		for (Integer num : nums) {
			addNum += num.intValue();
		}
		if (checkRoom && !checkRoom(player,items,addNum)) {
			return Constants.ADD_ITEM_NO_ROOM;
		}
		
		for (Integer itemId : itemIds) {
			int index = itemIds.indexOf(itemId);
			int num = nums.get(index);
			Item newItem = ItemMG.instance.itemFactory(itemId);
			if (newItem == null) {
				continue;
			}
			if (items.size() > 0) {
				if (hasItemMap.size() > 0 && hasItemMap.keySet().contains(itemId)) {
					newItem.setNum(hasItemMap.get(itemId).getNum() + num);
					hasItemMap.remove(itemId);
					newItems.add(newItem);
				}else {
					newItem.setNum(num);
					newItems.add(newItem);
				}
			}else {
				newItem.setNum(num);
				newItems.add(newItem);
			}
			sb.append(newItem.getId() + ":" + newItem.getNum() + "|");
		}
		if (hasItemMap.size() > 0) {
			for (Map.Entry<Integer, Item> oldMap : hasItemMap.entrySet()) {
				newItems.add(oldMap.getValue());
				sb.append(oldMap.getValue().getId() + ":" + oldMap.getValue().getNum() + "|");
			}
		}
		try {
			syncItems(player.getId(), newItems);
			log.debug(player.getSid() + "|" + player.getId() + "|" + "new items:[" + sb.toString() + "]!");
			return Constants.ADD_ITEM_SUCC;
		} catch (GException e) {
			e.printStackTrace();
			return Constants.ADD_ITEM_FAIL;
		}
	}
	
	/**
	 * 删除道具及其数量
	 * 
	 * @param player
	 * @param itemId
	 * @param num
	 * @return(5.行囊里面没有该道具;6.数量不够;7.删除道具成功;8.删除道具异常)
	 */
	public static int delItem(PlayerVo player, int itemId, int num) {
		ArrayList<Item> items = getAllItems(player.getId());
		ArrayList<Item> newItemList = new ArrayList<Item>();
		boolean hasItem = false;
		for (Item item : items) {
			if (item.getId().equals(itemId)) {
				if (checkNum(item,num)) {
					hasItem = true;
					log.debug("delete item[" + itemId + "] success!");
				}else {
					log.debug(itemId + "num is not enough!!");
					return Constants.DEL_ITEM_NOT_ENOUGH;
				}
				if (item.getNum() - num > 0) {
					item.setNum(item.getNum() - num);
				}else {
					continue;
				}
			}
			newItemList.add(item);
		}
		if (hasItem) {
			try {
				log.debug("delete item[" + itemId + "] and start save left items!");
				syncItems(player.getId(), newItemList);
				log.debug("delete item[" + itemId + "] and save left items success!");
				return Constants.DEL_ITEM_SUCC;
			} catch (GException e) {
				e.printStackTrace();
				return Constants.DEL_ITEM_FAIL;
			}
		}else {
			log.debug("there is no item:" + itemId);
			return Constants.DEL_ITEM_LACK;
		}
	}
	
	/**
	 * 批量删除道具列表及其数量列表
	 * 
	 * @param player
	 * @param itemIds
	 * @param nums
	 * @return(5.不存在此道具;6.数量不够;7.删除道具成功;8.删除道具异常)
	 */
	public static int delItems(PlayerVo player, List<Integer> itemIds, List<Integer> nums) {
		StringBuffer sb = new StringBuffer();
		ArrayList<Item> items = getAllItems(player.getId());
		ArrayList<Item> newItemList = new ArrayList<Item>();
		boolean enoughItems = false;
		for (Integer itemId : itemIds) {
			int index = itemIds.indexOf(itemId);
			int delNum = nums.get(index);
			sb.append(itemId + ":" + delNum + "|");
			for (Item item : items) {
				if (item.getId().equals(itemId)) {
					if (checkNum(item,delNum)) {
						enoughItems = true;
						log.debug(player.getSid() + "|" + player.getId() + "|" + "delete item[" + itemId + "] success!");
					}else {
						log.debug(itemId + "num is not enough!!");
						return Constants.DEL_ITEM_NOT_ENOUGH;
					}
					item.setNum(item.getNum() - delNum);
				}
				newItemList.add(item);
			}
		}
		if (enoughItems) {
			try {
				log.debug(player.getSid() + "|" + player.getId() + "|" + "delete items[" + sb.toString() + "] and start save left items!");
				syncItems(player.getId(), newItemList);
				log.debug(player.getSid() + "|" + player.getId() + "|" + "delete items[" + sb.toString() + "] and save left items success!");
				return Constants.DEL_ITEM_SUCC;
			} catch (GException e) {
				e.printStackTrace();
				return Constants.DEL_ITEM_FAIL;
			}
		}else {
			log.debug(player.getSid() + "|" + player.getId() + "|" + "there is no items:" + sb.toString());
			return Constants.DEL_ITEM_LACK;
		}
	}
	
	public static void syncItems(String playerId, ArrayList<Item> items) throws GException {
		try {
			log.debug(playerId + " sync items start...");
			itemCache.set(playerId, items);
			ProfileService.saveItems2DB(playerId, items);
			log.debug(playerId + " sync items success!!");
		} catch (GException e) {
			log.error(playerId + " sync items fail!!");
			throw new GException(e);
		}
	}
	
	/**
	 * 检测道具数量是否足够，不够返回false，够返回true
	 * 
	 * @param player
	 * @param item
	 * @return
	 */
	private static boolean checkNum(Item item, int num) {
		return item.getNum() >= num ? true : false;
	}
	
	/**
	 * 检查行囊空间是否够用，false表示空间不够，true表示够用
	 * 
	 * @param player
	 * @param items
	 * @return
	 */
	private static boolean checkRoom(PlayerVo player,List<Item> items, int num) {
		int sum = 0;
		for (Item item : items) {
			sum += item.getNum();
		}
		if (sum + num > player.getMaxRoom()) {
			return false;
		}
		return true;
	}
	
	/**
	 * 能否添加普通道具
	 * 
	 * @param playerId
	 * @param addNum
	 * @return
	 */
	public static boolean checkRoom(String sid,String playerId,int addNum) {
		PlayerVo player = PlayerService.doGetPlayer(sid, playerId);
		if (player == null) {
			return false;
		}
		ArrayList<Item> items = getAllItems(playerId);
		if (items == null && player.getMaxRoom() >= addNum) {
			return true;
		}
		int sum = 0;
		for (Item item : items) {
			sum += item.getNum();
		}
		if (sum + addNum > player.getMaxRoom()) {
			return false;
		}else {
			return true;
		}
	}
}
